#include<iostream>

#include<stdio.h>

#include<string>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include<string.h>

#include<unistd.h>

#include<vector>

#define SIZE 1024

struct task
{
    int skfd;
    sockaddr_in in;
};

int reconnect(task* tkptr)
{
    close(tkptr->skfd);
    tkptr->skfd = socket(AF_INET, SOCK_STREAM, 0);
    int cnt = 5;
    while(cnt)
    {
        int ret = connect(tkptr->skfd, (const sockaddr*)&(tkptr->in), sizeof(tkptr->in));
        if(ret < 0)
        {
            cnt--;
            std::cerr << "connect error..., reconnect: " << cnt << std::endl;
            sleep(1);
        }
        else
        {
            std::cerr << "connect success" << std::endl;
            return 0;
        }
    }
    return -1;
}

void* read_thread(void* arg)
{
    pthread_detach(pthread_self());
    task* tkptr = static_cast<task*>(arg);

    char buffer[SIZE] = {0};
    while(1)
    {
        int n = read(tkptr->skfd, buffer, SIZE);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cerr << buffer << std::endl;
        }
        else
        {
            if(reconnect(tkptr) < 0)
            {
                exit(1);
            }
            // else
            // {
            //     continue;
            // }
        }
    }
}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        std::cout << "3 words! error." << std::endl;
    }

    task tk;
    int16_t port = std::stoi(argv[2]);
    tk.in.sin_family = AF_INET;
    tk.in.sin_port = htons(port);
    tk.in.sin_addr.s_addr = inet_addr(argv[1]);

    tk.skfd = socket(AF_INET, SOCK_STREAM, 0);
    int cnt = 5;
    bool isconnected = false;
    
    connect(tk.skfd, (const sockaddr*)&(tk.in), sizeof(tk.in));

    pthread_t PT;
    pthread_create(&PT, nullptr, read_thread, (void*)&tk);

    std::string message;
    while(1)
    {
        std::cout << "please enter# ";
        std::getline(std::cin, message);
        write(tk.skfd, message.c_str(), message.size());
    }
}